package com.vcc.boss.core.queue.batch.recharge.queue;

import com.vcc.boss.core.queue.batch.recharge.model.RechargeQueueDto;
import com.vcc.channel.base.model.request.CardRechargeDto;
import com.vcc.channel.base.service.ChannelBaseService;
import com.vcc.data.entity.UserCard;
import com.vcc.service.service.TaskLogService;
import com.vcc.service.service.UserCardService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executors;

@Component
public class RechargeQueue implements CommandLineRunner {

    @Autowired
    private UserCardService userCardService;
    @Autowired
    private TaskLogService taskLogService;
    @Resource
    private ApplicationContext applicationContext;

    private static final Logger logger = LoggerFactory.getLogger(RechargeQueue.class);

    private volatile DelayQueue<RechargeQueueDto> delayQueue = new DelayQueue<RechargeQueueDto>();


    public void add(String orderId, String cardNumber, BigDecimal amount, Integer index, Integer targetIndex) {
        synchronized (this) {
            RechargeQueueDto rechargeQueueDto = delayQueue.stream().filter(it -> it.getCardNumber().equals(cardNumber) && it.getOrderId().equals(orderId)).findFirst().orElse(null);
            if (rechargeQueueDto == null) {
                LocalDateTime now = LocalDateTime.now();
                LocalDateTime nowB = now.plusSeconds(5L);
                long betweenMillis = ChronoUnit.MILLIS.between(now, nowB);
                logger.info("当前添加的是${orderId},秒${time}");
                delayQueue.put(
                        new RechargeQueueDto(
                                orderId, cardNumber, System.currentTimeMillis() + betweenMillis, amount, index, targetIndex
                        )
                );
            }
        }
    }


    @Override
    public void run(String... args) throws Exception {
        Executors.newSingleThreadExecutor().execute(new Thread(this::excuteThread));
    }

    private void excuteThread() {
        while (true) {
            try {
                processTask(delayQueue.take());
            } catch (InterruptedException e) {
                break;
            }
        }
    }

    /**
     * 内部执行延时任务
     *
     * @param rechargeQueueDto
     */
    private void processTask(RechargeQueueDto rechargeQueueDto) {
        try {
            logger.info("当前处理的卡是{}", rechargeQueueDto.getCardNumber());
            UserCard userCard = userCardService.getByCardNumber(rechargeQueueDto.getCardNumber());
            ChannelBaseService channelBaseService = applicationContext.getBean(userCard.getChannelCode(),ChannelBaseService.class);
            channelBaseService.recharge(
                    CardRechargeDto.builder()
                            .channelCardId(userCard.getChannelCardId())
                            .rechargeAmount(rechargeQueueDto.getAmount())
                            .requestId(rechargeQueueDto.getOrderId())
                            .cardNumberId(userCard.getId())
                            .cardNumber(userCard.getCardNumber())
                            .build()
            );
            taskLogService.processedSuccess(rechargeQueueDto.getOrderId());
            if (rechargeQueueDto.getIndex().equals(rechargeQueueDto.getTargetIndex())) {
                taskLogService.processedAccomplish(rechargeQueueDto.getOrderId());
            }
        } catch (Exception e) {
            taskLogService.processedError(rechargeQueueDto.getOrderId());
            logger.error("异常", e);
        }
    }
}
